//=============================================================================
// File name:   seg7_top.v
// Author:      Cody Cziesler
//
// Description: This module will act as the control for the seven-segment 
//              display circuit. It is able to...
//
//                1) Multiplex the outputs based on an up-counter (based 
//                   on the clk)
//
//                2) Set an individual number on a segment
//
//                3) Reset the circuit back to its original state
//
//=============================================================================
`include "include.v"

module seg7_top (
  input  wire       clk,        // The clock that will switch between anodes
  input  wire       rst_n,      // An active-low reset
  input  wire       set,        // An active-high set - when high, bin_seg_* will be set to seg_in based on anode_in
  input  wire [3:0] seg_in,     // Used to set bin_seg_*
  input  wire [1:0] anode_in,   // Used to set bin_seg_*
  output reg  [3:0] anode_out,  // The active-low anode to display
  output reg  [6:0] seg_out,    // The active-low cathode to display
  output wire       dp          // The decimal point cathode
);

// 7-seg decoded numbers
wire [6:0] seg_a;    // output for first  7-seg display
wire [6:0] seg_b;    // output for second 7-seg display
wire [6:0] seg_c;    // output for third  7-seg display
wire [6:0] seg_d;    // output for fourth 7-seg display

// Registers to hold the four-bit binary number (pre-decode)
reg [3:0] bin_seg_a; // Number for the first  7-seg display
reg [3:0] bin_seg_b; // Number for the second 7-seg display
reg [3:0] bin_seg_c; // Number for the third  7-seg display
reg [3:0] bin_seg_d; // Number for the fourth 7-seg display

// A counter to select which digit to light up
reg [1:0] anode_sel;

// The decimal point value (assuming it is always off)
assign dp = ~1'b0;

// When set is high, bin_seg_* will be set, depending on anode_in
always @(posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    bin_seg_a <= 4'h0;
    bin_seg_b <= 4'h0;
    bin_seg_c <= 4'h0;
    bin_seg_d <= 4'h0;
  end else begin
    if (set) begin
      case (anode_in)
        2'b00 : bin_seg_a <= seg_in;
        2'b01 : bin_seg_b <= seg_in;
        2'b10 : bin_seg_c <= seg_in;
        2'b11 : bin_seg_d <= seg_in;
      endcase
    end
  end
end

// 2-bit up-counter for anode_sel
always @(posedge clk or negedge rst_n) begin
  if (!rst_n) begin
    anode_sel <= 2'h0;
  end else begin
    anode_sel <= anode_sel + 1'b1;
  end
end

// Mux the output cathode depending on the up-counter
always @(*) begin
  case (anode_sel)
    2'h0 :    seg_out = seg_a;
    2'h1 :    seg_out = seg_b;
    2'h2 :    seg_out = seg_c;
    2'h3 :    seg_out = seg_d;
    default:  seg_out = `SEG_0;
  endcase
end

// Mux the output anode depending on the up-counter
always @(*) begin
  case (anode_sel)
    2'h0 :    anode_out = `AN_1;
    2'h1 :    anode_out = `AN_2;
    2'h2 :    anode_out = `AN_3;
    2'h3 :    anode_out = `AN_4;
    default : anode_out = `AN_1;
  endcase
end

// Decoders for each segment
seg7_decode a_seg7_decode (
  .en(1'b1),
  .seg_in(bin_seg_a),
  .seg_out(seg_a)
);

seg7_decode b_seg7_decode (
  .en(1'b1),
  .seg_in(bin_seg_b),
  .seg_out(seg_b)
);

seg7_decode c_seg7_decode (
  .en(1'b1),
  .seg_in(bin_seg_c),
  .seg_out(seg_c)
);

seg7_decode d_seg7_decode (
  .en(1'b1),
  .seg_in(bin_seg_d),
  .seg_out(seg_d)
);

endmodule
